const PEDDING = 'pedding'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
    constructor(executor) {
        try {
            executor(this.resolve, this.reject)
        } catch(error) {
            this.reject(error)
        }
        
    }

    state = PEDDING
    value = null //成功之后的值
    reason = null //失败之后的原因
    onFulfilledCallbacks = [] //存储成功回调
    onRejectedCallbacks = [] //存储失败回调

    resolve = (value) => {
        if (this.state === PEDDING) {
            this.state = FULFILLED
            this.value = value
            while (this.onFulfilledCallbacks.length) {
                this.onFulfilledCallbacks.shift()(value)
            }
        }
    }

    reject = (reason) => {
        if (this.state === PEDDING) {
            this.state = REJECTED
            this.reason = reason
            while (this.onFulfilledCallbacks.length) {
                this.onFulfilledCallbacks.shift()(reason)
            }
        }
    }

    then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason => reason

        const promise2 = new MyPromise((resolve, reject) => {
            const fulfilledMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = onFulfilled(this.value);
                        // 传入 resolvePromise 集中处理
                        resolvePromise(promise2, x, resolve, reject);
                    } catch(error) {
                        reject(error)
                    }
                })
            }

            const rejectedMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = onRejected(this.reason)
                        // 传入 resolvePromise 集中处理
                        resolvePromise(promise2, x, resolve, reject);
                    } catch(error) {
                        reject(error)
                    }
                })
            }
            if (this.state === FULFILLED) {
                fulfilledMicrotask()
                
            } else if (this.state === REJECTED) {
                rejectedMicrotask()
                
            } else if (this.state === PEDDING) {
                this.onFulfilledCallbacks.push(fulfilledMicrotask)
                this.onRejectedCallbacks.push(rejectedMicrotask)
            }
        })
        return promise2
    }

    static resolve(parameter) {
        if(parameter instanceof MyPromise) {
            return parameter
        }
        return new MyPromise((resolve, reject) => {
            resolve(parameter)
        })
    }

    static reject(reason) {
        return new MyPromise((resolve, reject) => {
            reject(reason)
        })
    }
}

function resolvePromise(promise2, x, resolve, reject) {
    if(promise2 === x) {
        throw new TypeError('Chaining cycle detected for promise #<Promise>')
    }
    // 判断x是不是 MyPromise 实例对象
    if (x instanceof MyPromise) {
        // x.then(value => resolve(value), reason => reject(reason))
        // 简化之后
        x.then(resolve, reject)
    } else {
        // 普通值
        resolve(x)
    }
}

MyPromise.deferred = function () {
    var result = {};
    result.promise = new MyPromise(function (resolve, reject) {
      result.resolve = resolve;
      result.reject = reject;
    });
  
    return result;
  }
  
  module.exports = MyPromise;